package com.af.monitorModule.controller.websocket;

import com.af.monitorModule.controller.statistics.DataController;
import com.af.monitorModule.generator.mapper.CompanyMapper;
import com.af.monitorModule.generator.mapper.TimedTaskResultMapper;
import com.af.monitorModule.generator.service.ServerPushService;
import com.af.monitorModule.generator.service.ServerService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lyz
 */
@ServerEndpoint(value = "/ws/ComputerLine")
@Component
public class ComputerLineSocket {

    private static final Logger logger = LoggerFactory.getLogger(ComputerLineSocket.class);

    private static final AtomicInteger ON_LINE_COUNT = new AtomicInteger(0);

    private static final CopyOnWriteArraySet<Session> SESSION_SET = new CopyOnWriteArraySet<>();

    private boolean cpuOrMem = true;

    @Autowired
    private ServerPushService serverPushService;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private ServerService serverService;


    @Autowired
    private TimedTaskResultMapper timedTaskResultMapper;


    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        SESSION_SET.add(session);
        int cnt = ON_LINE_COUNT.incrementAndGet();
        logger.info("有连接加入，id={}，当前连接数为：{}", session.getId(), cnt);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        SESSION_SET.remove(session);
        int cnt = ON_LINE_COUNT.decrementAndGet();
        logger.info("有连接关闭，当前连接数为：{}", cnt);
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     *            客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
    }

    /**
     * 出现错误
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("发生错误：{}，Session ID： {}",error.getMessage(),session.getId());
        logger.error("info is ", error);
    }


    /**
     * 发送消息，实践表明，每次浏览器刷新，session会发生变化。
     */
    public static void sendMessage(Session session, String message) {
        session.getAsyncRemote().sendText(message);
    }

    /**
     * 群发消息
     */
    public static void broadCastInfo(String message){
        for (Session session : SESSION_SET) {
            if(session.isOpen()){
                sendMessage(session, message);
            }
        }
    }

    /**
     * 指定Session发送消息
     */
    public static void sendMessage(String message,String sessionId){
        Session session = null;
        for (Session s : SESSION_SET) {
            if(s.getId().equals(sessionId)){
                session = s;
                break;
            }
        }
        if(session!=null){
            sendMessage(session, message);
        }
        else{
            logger.warn("没有找到你指定ID的会话：{}",sessionId);
        }
    }



    @Scheduled(cron = "0/5 * * * * ? ")
    public void need2Send(){

        List<JSONObject> newResultInfo = timedTaskResultMapper.getTenMinutesInfo();
        JSONObject info;
        // true 是CPU信息  false 是内存信息
        if (cpuOrMem){
            info = cpu(newResultInfo);
        }else {
            info = memory(newResultInfo);
        }
        broadCastInfo(new JSONObject(){{
            put("or",cpuOrMem);
            put("data",info);
        }}.toJSONString());
        cpuOrMem = !cpuOrMem;
    }

    private JSONObject cpu(List<JSONObject> newResultInfo){
        JSONObject jsonObject = newResultInfo.stream().max((k, v) -> {
            double sub = k.getDoubleValue("cpu") - v.getDoubleValue("cpu");
            if (sub > 0) return 1;
            if (sub < 0) return -1;
            return 0;
        }).get();
        JSONObject server_id = serverPushService.getShowLine(jsonObject.get("server_id").toString(), "1");
        server_id.put("company",serverService.findCompanyByServerId(jsonObject.get("server_id").toString()));
        server_id.put("server",serverService.getById(jsonObject.get("server_id").toString()));
        return server_id;
    }

    private JSONObject memory(List<JSONObject> newResultInfo){
        JSONObject jsonObject = newResultInfo.stream().max((k, v) -> {
            double sub = k.getDoubleValue("memory") - v.getDoubleValue("memory");
            if (sub > 0) return 1;
            if (sub < 0) return -1;
            return 0;
        }).get();
        JSONObject server_id = serverPushService.getShowLine(jsonObject.get("server_id").toString(), "1");
        server_id.put("company",serverService.findCompanyByServerId(jsonObject.get("server_id").toString()));
        server_id.put("server",serverService.getById(jsonObject.get("server_id").toString()));
        return server_id;
    }
}
